unit uSound;

interface

uses Bass, Classes; 

const
  mcMenu   = 1; // Menu music
  mcGame   = 2; // Game music
  mcClick  = 3; // Mouse click sound

var
  FF: Boolean = True;

type
  TChannelType = (ctUnknown, ctStream, ctMusic);
  
  TSound = class(TObject)
  private
    FC: Byte;
    FChannelType: TChannelType;
    FTmpList, FSoundsList: TStringList;
    FChannel: array[-1..7] of DWORD;
    FVolume: ShortInt;
    IsPlayMusic: Boolean;
    procedure SetVolume(Value: ShortInt);
    function GetVolume: ShortInt;
  public
    constructor Create;
    destructor Destroy; override;
    property Volume: ShortInt read GetVolume write SetVolume;
    function Play(const SoundID: Integer): Boolean; overload;
    function Play(const FileName: string): Boolean; overload;
    function PlayMusic(const SoundID: Integer): Boolean;
    procedure Stop();
    procedure StopMusic();
  end;

var
  Sound: TSound;

implementation

uses SysUtils, Dialogs;

{ TSound }

constructor TSound.Create;
var
  I: Integer;    
  BassInfo: BASS_INFO;
begin
  Volume := 50;
  BASS_Init(1, 44100, BASS_DEVICE_3D, 0, nil);
  BASS_Start;
  BASS_GetInfo(BassInfo);
  FSoundsList := TStringList.Create;
  FTmpList := TStringList.Create;
  FTmpList.LoadFromFile('config\sound.ini');
  for i := 0 to FTmpList.Count - 1 do
    if (Trim(FTmpList[i]) <> '') then
      FSoundsList.Append(Trim(FTmpList[i]));
  FTmpList.Free;
end;

destructor TSound.Destroy;
begin
  Stop();
  FSoundsList.Free;
  inherited;
end;

function TSound.GetVolume: ShortInt;
begin
  if (FVolume > 100) then FVolume := 100;
  if (FVolume < 0) then FVolume := 0;
  Result := FVolume;
end;

function TSound.Play(const FileName: string): Boolean;
begin
  Result := False;
  if (Volume <= 0) then Exit;
  FChannel[FC] := BASS_StreamCreateFile(False, PChar(FileName), 0, 0, 0);
  if (FChannel[FC] <> 0) then
  begin
    FChannelType := ctStream;
    BASS_ChannelSetAttribute(FChannel[FC], BASS_ATTRIB_VOL, Volume / 100);
    BASS_ChannelPlay(FChannel[FC], False);
  end;
  Result := FChannel[FC] <> 0;
  Inc(FC);
  if (FC > High(FChannel)) then FC := 0;
end;

function TSound.Play(const SoundID: Integer): Boolean;
var
  S: string;
begin
  S := FSoundsList[SoundID - 1];
  S := Copy(S, Pos('=', S) + 1, Length(S));
  Result := Play(Trim(S));
end;

function TSound.PlayMusic(const SoundID: Integer): Boolean;
var
  S: string;
begin
  Result := False;
  if (Volume <= 0) or IsPlayMusic then Exit;
  S := FSoundsList[SoundID - 1];
  S := Copy(S, Pos('=', S) + 1, Length(S));
  FChannel[-1] := BASS_StreamCreateFile(False, PChar(Trim(S)), 0, 0, 0);
  if (FChannel[-1] <> 0) then
  begin
    FChannelType := ctStream;
    BASS_ChannelSetAttribute(FChannel[-1], BASS_ATTRIB_VOL, Volume / 100);
    BASS_ChannelPlay(FChannel[-1], False);
  end;
  Result := FChannel[-1] <> 0;
  IsPlayMusic := True;
end;

procedure TSound.SetVolume(Value: ShortInt);
begin
  if (Value > 100) then Value := 100;
  if (Value < 0) then Value := 0;
  FVolume := Value;
end;

procedure TSound.Stop;
var
  I: Byte;
begin
  for I := 0 to High(FChannel) do
    BASS_ChannelStop(FChannel[I]);
end;

procedure TSound.StopMusic;
begin
  IsPlayMusic := False;
  BASS_ChannelStop(FChannel[-1]);
end;

initialization
  Sound := TSound.Create;
  Sound.Volume := 100;

finalization
  Sound.Stop;
  Sound.Free;

end.

